﻿using System;
using Styx;
using Styx.Helpers;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace TuanHA_Monk_Special_Edition_Extreme_PvP
{
    public partial class Classname
    {
        #region Delegates

        public delegate float DynamicRangeRetriever(object context);

        public delegate WoWPoint LocationRetriever(object context);

        public delegate bool SimpleBooleanDelegate(object context);

        public delegate WoWUnit UnitSelectionDelegate(object context);

        #endregion

        public bool IsMovingBehind = false;
        public static TimeSpan MovementDelay = TimeSpan.FromSeconds(0);
        public DateTime LastMovementTime = new DateTime(1970, 1, 1);
        //public WoWPoint LastMovementWoWPoint = Me.Location;
        public WoWPoint LastMovementWoWPoint;
        public static float DistanceToUpdateMovement = 3f;
        public static float DistanceToMelee;

        //Set Distance To Keep in Melee Range base on Unit type
        public float Dtm(WoWUnit toUnit)
        {
            if (toUnit.IsPlayer)
            {
                return 3;
            }
            return 5;
        }

        public Composite MovementMoveStop(UnitSelectionDelegate toUnit, double range)
        {
            return new Decorator(
                ret =>
                THSettings.Instance.AutoMove &&
                !IsOverrideModeOn &&
                toUnit != null &&
                toUnit(ret) != null &&
                toUnit(ret) != Me &&
                toUnit(ret).IsAlive &&
                Me.IsMoving &&
                (!toUnit(ret).IsMoving &&
                 toUnit(ret).Location.Distance(Me.Location) - toUnit(ret).BoundingRadius <= Dtm(toUnit(ret)) ||
                 toUnit(ret).Location.Distance(Me.Location) - toUnit(ret).BoundingRadius <= 1),
                new Action(ret =>
                               {
                                   //if (DateTime.Now < MovementDelay && !Me.IsBehind(toUnit(ret)))
                                   //{
                                   //    Logging.Write(LogLevel.Diagnostic,
                                   //                  DateTime.Now.ToString("ss:fff ") + "IsMovingBehind");
                                   //    return RunStatus.Failure;
                                   //}
                                   Navigator.PlayerMover.MoveStop();
                                   //Logging.Write(LogLevel.Diagnostic,
                                   //              DateTime.Now.ToString("ss:fff ") + "MovementMoveStop");
                                   return RunStatus.Failure;
                               }));
        }

        public Composite MovementMoveToLoS(UnitSelectionDelegate toUnit)
        {
            return new Decorator(
                ret =>
                THSettings.Instance.AutoMove &&
                DateTime.Now > DoNotMove &&
                !IsOverrideModeOn &&
                !Me.IsCasting &&
                //!Me.IsChanneling &&
                toUnit != null &&
                toUnit(ret) != null &&
                toUnit(ret) != Me &&
                //Only Move again After a certain delay or target move 3 yard from original posision
                (LastMovementTime + MovementDelay < DateTime.Now ||
                 LastMovementWoWPoint.Distance(toUnit(ret).Location) >
                 DistanceToUpdateMovement) &&
                !toUnit(ret).InLineOfSpellSight,
                new Action(ret =>
                               {
                                   LastMovementWoWPoint = toUnit(ret).Location;
                                   Navigator.MoveTo(LastMovementWoWPoint);
                                   //Logging.Write(LogLevel.Diagnostic,
                                   //              DateTime.Now.ToString("ss:fff ") + "MovementMoveToLoS");
                                   LastMovementTime = DateTime.Now;
                                   return RunStatus.Failure;
                               }));
        }

        public Composite MovementMoveToMelee(UnitSelectionDelegate toUnit)
        {
            return new Decorator(
                ret =>
                THSettings.Instance.AutoMove &&
                DateTime.Now > DoNotMove &&
                !IsOverrideModeOn &&
                !Me.IsCasting &&
                //!Me.IsChanneling &&
                toUnit != null &&
                toUnit(ret) != null &&
                toUnit(ret) != Me &&
                toUnit(ret).IsAlive &&
                //Only Move again After a certain delay or target move 3 yard from original posision
                (DateTime.Now > LastMovementTime + MovementDelay ||
                 LastMovementWoWPoint.Distance(toUnit(ret).Location) >
                 DistanceToUpdateMovement) &&
                (toUnit(ret).Distance - toUnit(ret).BoundingRadius > Dtm(toUnit(ret)) || !toUnit(ret).IsWithinMeleeRange),
                new Action(ret =>
                               {
                                   LastMovementWoWPoint = toUnit(ret).Location;
                                   Navigator.MoveTo(LastMovementWoWPoint);
                                   //Logging.Write(LogLevel.Diagnostic,
                                   //              DateTime.Now.ToString("ss:fff ") + "MovementMoveToMelee");

                                   //I'm just a stupid
                                   //Logging.Write(LogLevel.Diagnostic,
                                   //              (LastMovementTime + MovementDelay).ToString("yyyy-mm-dd hh:mm:ss:fff ") +
                                   //              "LastMovementTime + MovementDelay");
                                   //Logging.Write(LogLevel.Diagnostic,
                                   //              DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff ") + "DateTime.Now");
                                   //if (DateTime.Now > LastMovementTime + MovementDelay)
                                   //{
                                   //    Logging.Write("DateTime.Now > LastMovementTime + MovementDelay " +
                                   //                  DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff > ") +
                                   //                  (LastMovementTime + MovementDelay).ToString(
                                   //                      "yyyy-mm-dd hh:mm:ss:fff "));
                                   //}

                                   //if (DateTime.Now < LastMovementTime + MovementDelay)
                                   //{
                                   //    Logging.Write("DateTime.Now < LastMovementTime + MovementDelay " +
                                   //                  DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:fff < ") +
                                   //                  (LastMovementTime + MovementDelay).ToString(
                                   //                      "yyyy-mm-dd hh:mm:ss:fff "));
                                   //}

                                   LastMovementTime = DateTime.Now;
                                   return RunStatus.Failure;
                               }));
        }

        public Composite MovementMoveBehind(UnitSelectionDelegate toUnit)
        {
            return
                new Decorator(
                    ret =>
                    THSettings.Instance.AutoMove &&
                    DateTime.Now > DoNotMove &&
                    !IsOverrideModeOn &&
                    !Me.IsCasting &&
                    //!Me.IsChanneling &&
                    toUnit != null &&
                    toUnit(ret) != null &&
                    toUnit(ret) != Me &&
                    toUnit(ret).IsAlive &&
                    //only MovementMoveBehind if IsWithinMeleeRange
                    !toUnit(ret).IsMoving &&
                    toUnit(ret).Distance < Dtm(toUnit(ret)) &&
                    !Me.IsBehind(toUnit(ret)) &&
                    !MeIsTank &&
                    //Only Move again After a certain delay or target move 3 yard from original posision
                    (DateTime.Now > LastMovementTime + MovementDelay ||
                     LastMovementWoWPoint.Distance(toUnit(ret).Location) >
                     DistanceToUpdateMovement) &&
                    (toUnit(ret).IsPlayer ||
                     !toUnit(ret).IsPlayer && toUnit(ret).CurrentTarget != Me && toUnit(ret).Combat),
                    new Action(ret =>
                                   {
                                       WoWPoint pointBehind =
                                           toUnit(ret).Location.RayCast(
                                               toUnit(ret).Rotation + WoWMathHelper.DegreesToRadians(150), 3f);
                                       LastMovementWoWPoint = pointBehind;

                                       Navigator.MoveTo(pointBehind);
                                       //Logging.Write(LogLevel.Diagnostic,
                                       //              DateTime.Now.ToString("ss:fff ") + "MovementMoveBehind");
                                       //Logging.Write(LogLevel.Diagnostic, "IsMovingBehind = true");
                                       LastMovementTime = DateTime.Now;
                                       return RunStatus.Failure;
                                   }));
        }
    }
}